package com.neo.code.lucene.demo01;

import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author baiyp
 */
@Slf4j
public class Indexer {

    private IndexWriter writer;

    public Indexer(String indexDirectoryPath) throws IOException {
        // this directory will contain the indexes
        Directory indexDirectory = FSDirectory.open(new File(indexDirectoryPath));
        // create the indexer
        writer = new IndexWriter(indexDirectory,
                new StandardAnalyzer(Version.LUCENE_36), true,
                IndexWriter.MaxFieldLength.UNLIMITED);
    }

    public void close() throws CorruptIndexException, IOException {
        writer.close();
    }

        private Document getDocument(File file) throws IOException {
            Document document = new Document();
            // index file contents
            Field contentField = new Field(Constants.CONTENTS, new FileReader(file));
            // index file name
            Field fileNameField = new Field(Constants.FILE_NAME, file.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED);
            // index file path
            Field filePathField = new Field(Constants.FILE_PATH, file.getCanonicalPath(), Field.Store.YES, Field.Index.NOT_ANALYZED);
            // index file length
            Field fileLengthField = new Field(Constants.FILE_LENGTH, file.length() + "", Field.Store.YES, Field.Index.NOT_ANALYZED);
            document.add(contentField);
            document.add(fileNameField);
            document.add(filePathField);
            document.add(fileLengthField);
            return document;
        }

    private void indexFile(File file) throws IOException {
        log.info("index -> " + file.getCanonicalPath() + "[" + file.length() + "]");
        Document document = getDocument(file);
        writer.addDocument(document);
    }

    private void deleteFile(String name) throws IOException {
        writer.deleteDocuments(new PrefixQuery(new Term(Constants.FILE_NAME, name)));
        writer.commit();
    }

    public int addDocs(String dataDirPath, FileFilter filter) throws IOException {
        // get all files in the data directory
        File[] files = new File(dataDirPath).listFiles();
        log.info("[indexing files]");
        for (File file : files) {
            if (!file.isDirectory() && !file.isHidden() && file.exists() && file.canRead() && filter.accept(file)) {
                indexFile(file);
            }
        }
        return writer.numDocs();
    }

    public int deleteIndex(String name) throws IOException {
        deleteFile(name);
        return writer.numDocs();
    }
}
